package com.wan37.client.service;

import com.wan37.client.handler.ClientHandler;
import com.wan37.client.service.cache.RoleServiceCache;
import com.wan37.client.service.cache.TeamCache;
import com.wan37.client.service.cache.UserServiceCache;
import com.wan37.protobuf.constant.AllRoleLabel;
import com.wan37.protobuf.constant.SkillLabel;
import com.wan37.protobuf.message.client2server.game.GameEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 玩家和boss之间的战斗
 *
 * @author : luoyong
 * @date : 2020-07-02 09:31
 **/
@Component("pVEFightingService")
public class PVEFightingService implements FightingService {

    private ClientHandler clientHandler = ClientHandler.getInstance();
    private final static Logger logger = LoggerFactory.getLogger(PVEFightingService.class);
    @Autowired
    private UserServiceCache userServiceCache;
    @Autowired
    private RoleServiceCache roleServiceCache;
    @Autowired
    private TeamCache teamCache;
    public static int index = 0;
    /**
     * boss场景战斗线程池，方便停止战斗
     */
    public final static Map<String, ThreadPoolExecutor> sceneNameToExecutor = new ConcurrentHashMap<>();

    @Override
    public void fighting() {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2, 3, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100), r -> {
            Thread thread = new Thread(r);
            thread.setName("玩家和boss对战技能线程池");
            thread.setDaemon(true);
            return thread;
        });
        ThreadPoolExecutor threadPool1 = new ThreadPoolExecutor(
                2, 3, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100), r -> {
            Thread thread = new Thread(r);
            thread.setName("玩家和boss对战技能线程池");
            thread.setDaemon(true);
            return thread;
        });
        sceneNameToExecutor.put(clientHandler.selfId, threadPool);
        sceneNameToExecutor.put(clientHandler.current_scene, threadPool1);
        List<GameEntity.Role> roleList = new ArrayList<>();
        List<GameEntity.AllRole> monsterList = new ArrayList<>();

        for (String roleId : userServiceCache.getUserInMap().get(clientHandler.selfId).getRoleIdList()) {
            roleList.add(roleServiceCache.getRoleInMap().get(roleId).getRole());
            for (GameEntity.Skill skill : roleServiceCache.getRoleInMap().get(roleId).getSkillMap().values()) {
                DelayThreadPool.initAdd(roleId, skill);
            }
        }

        for (GameEntity.AllRole allRole : ClientHandler.allRoleMap.values()) {
            if (allRole.getLabel() == AllRoleLabel.MONSTER) {
                monsterList.add(allRole);
                if (SkillService.allRoleIdToSkillMap.containsKey(allRole.getAllRoleId())){
                    for (GameEntity.Skill skill : SkillService.allRoleIdToSkillMap.get(allRole.getAllRoleId()).values()) {
                        DelayThreadPool.initAdd(allRole.getAllRoleId(), skill);
                    }
                }
            }
        }

        //当前战斗的boss
        GameEntity.AllRole monster = monsterList.get(index);
        for (GameEntity.Role role : roleList) {
            playerAttackMonster(role, monster);
        }
        /**
         * boss选择攻击对象
         */
        monsterSelectAttackObject(monster);

    }

    public void playerAttackMonster(GameEntity.Role role, GameEntity.AllRole monster) {
        if (role.getUserId().equals(clientHandler.selfId)){
            sceneNameToExecutor.get(clientHandler.selfId).execute(() -> {
//                logger.info("一次用户攻击怪物---------------------------------------");
                if (role.getAllRole().getStatus() == AllRoleLabel.STATUS_DIE) {
                    logger.info("角色{} 已经死亡不能攻击！", role.getAllRole().getNickname());
                    return;
                }
                if (monster.getStatus() == AllRoleLabel.STATUS_DIE) {
                    logger.info("boss{} 已经死亡不能被攻击！", monster.getNickname());
                    return;
                }
                GameEntity.Skill skill = SkillService.getPbqSkill(role.getAllRole().getAllRoleId());
                if (skill != null) {
                    if (role.getAllRole().getHP() - skill.getCostHP() < 0) {
                        logger.info(role.getAllRole().getNickname() + " 使用 " +
                                skill.getName() + " 技能失败，HP不够 ");
                        DelayThreadPool.add(role.getAllRole().getAllRoleId(), skill, 2);
                    } else {
                        if (skill.getLabel().startsWith(SkillLabel.ENEMY, 1)) {
                            clientHandler.sendAttackMessage(role.getAllRole().getAllRoleId(), monster.getAllRoleId(), skill.getId());
                            logger.info(role.getAllRole().getNickname() + " 使用 " +
                                    skill.getName() + " 技能攻击了 " + monster.getNickname());
                        } else {
                            clientHandler.sendAttackMessage(role.getAllRole().getAllRoleId(), role.getAllRole().getAllRoleId(), skill.getId());
                            logger.info(role.getAllRole().getNickname() + " 使用 " +
                                    skill.getName() + " 技能提升了 " + role.getAllRole().getNickname());
                        }
                    }
                }
            });
        }
    }

    public void monsterAttackPlayer(GameEntity.Role role, GameEntity.AllRole monster) {
        if(!role.getUserId().equals(clientHandler.selfId)){
            return;
        }
        sceneNameToExecutor.get(clientHandler.current_scene).execute(() -> {
//            logger.info("-----------------------------一次怪物攻击用户");
            if (role.getAllRole().getStatus() == AllRoleLabel.STATUS_DIE) {
                logger.info("角色{} 已经死亡不能被攻击！", role.getAllRole().getNickname());
                return;
            }
            if (monster.getStatus() == AllRoleLabel.STATUS_DIE) {
                logger.info("boss{} 已经死亡不能攻击！", monster.getNickname());
                return;
            }
            GameEntity.Skill skill = SkillService.getPbqSkill(monster.getAllRoleId());
            if (skill != null) {
                if (monster.getHP() - skill.getCostHP() < 0) {
                    logger.info(monster.getNickname() + " 使用 " +
                            skill.getName() + " 技能失败，HP不够 ");
                    DelayThreadPool.add(monster.getAllRoleId(), skill, 2);
                } else {
                    clientHandler.sendAttackMessage(monster.getAllRoleId(),
                            role.getAllRole().getAllRoleId(), skill.getId());
                    logger.info(monster.getNickname() + " 使用 " +
                            skill.getName() + " 技能攻击了 " + role.getAllRole().getNickname());
                }
            }
        });
    }

    public void monsterSelectAttackObject(GameEntity.AllRole monster) {
        /**
         * 判断优先攻击集合里面是否有值,没有就随便取一个存活攻击
         */
        if (monster.getAttackEntityIdList() != null && !monster.getAttackEntityIdList().isEmpty()) {
            for (GameEntity.stringMsg stringMsg : monster.getAttackEntityIdList()) {
                GameEntity.Role role = roleServiceCache.getRoleInMap().get(stringMsg.getStringId()).getRole();
                if (role.getAllRole().getStatus() == AllRoleLabel.STATUS_LIFE) {
                    monsterAttackPlayer(role, monster);
                    break;
                }
            }
        } else {
            for (UserServiceCache.UserIn userIn : userServiceCache.getUserInMap().values()){
                List<String> roleIdList = userIn.getRoleIdList();
                for (int i = roleIdList.size() - 1; i >= 0; i--) {
                    GameEntity.Role role = roleServiceCache.getRoleInMap().get(roleIdList.get(i)).getRole();
                    if (role.getAllRole().getStatus() == AllRoleLabel.STATUS_LIFE) {
                        monsterAttackPlayer(role, monster);
                        return;
                    }
                }
            }
        }
    }
    public void shutDownExecutor(){
        if (sceneNameToExecutor.containsKey(clientHandler.current_scene)){
            sceneNameToExecutor.get(clientHandler.current_scene).shutdownNow();
        }
        if (sceneNameToExecutor.containsKey(clientHandler.selfId)){
            sceneNameToExecutor.get(clientHandler.selfId).shutdownNow();
        }
    }
}
